#include <iostream>
#include <map>
#include <iterator>
#include <vector>
#include <string>

#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string.hpp>
#include<boost/tokenizer.hpp>
#include "stdfconfig.h"


using namespace boost::algorithm;
using namespace opsrc::stdf;
using namespace std;

static void removeAllWhite (string &str)
{
    std::string temp;
    for (unsigned int i = 0; i < str.length(); i++)
        if (str[i] != ' ') temp += str[i];
    str = temp;
}

static void toStrUpper(string &str)
{
    std::string temp;
    for (unsigned int i = 0; i < str.length(); i++)
        temp += toupper(str[i]);
    str = temp;
}

StdfConfig * StdfConfig::inst = 0;
StdfConfig::StdfConfig()
    : sOutputMode("")
{
    stdfFieldsRecSettingInitializeAs(true);

}

StdfConfig* StdfConfig::instance()
{
    if( inst == 0){
        inst = new StdfConfig;
    }
    return inst;
}

void StdfConfig::setConfigFile(const string s)
{
    string line;
    ifile.open(s.c_str());
    if( ifile.is_open())
    {
        while ( ifile.good() )
        {
            getline (ifile,line);
            removeAllWhite(line);
            if(!line.empty())
            {
                //std::cout << line << std::endl;
                if( line[0] != '#')
                {
                    int pos = line.find("=");
                    int len = line.length() - pos;
                    //string tmp = line.substr (pos+1, len);
                  //  std::cout << tmp << std::endl;
                    updateSetting( line.substr(0, pos), line.substr (pos+1, len));
                }
            }
        }
    }
    ifile.close();
}

void StdfConfig::updateSetting(const string _type, const string _sval)
{
    string type = _type;
    string sval = _sval;
    toStrUpper(type);
    toStrUpper(sval);

    if(type == "DEST_DIR")
    {
        sDesDir = _sval + '/';
    }
    else if(type == "SRC_DIR")
    {
        sSrcDir = _sval + '/';
    }
    else if(type == "FILENAME")
    {
        sFileName  = _sval;
        removeAllWhite(sFileName);
    }
    else if(type == "OUT_MODE")
    {
        if( "D_PRINT" == _sval || "D_FILE" == _sval )
            sOutputMode = _sval;
        else sOutputMode = "D_FILE";
    }
    else if( type == "TEST_NUM")
    {
        int tnum ;
        vector<string> f;
        std::string val = _sval;
        test_numbers_setting.clear();
        split( f, val, is_any_of(","), token_compress_on );
        if ((int)f.size()>0) {
            for (int i=0; i< (int)f.size(); i++) {
                trim(f[i]);
                tnum = atoi( (f[i]).c_str() );
                if(tnum > 0) {
                    test_numbers_setting.push_back(tnum);
                }
            }
        }
    }
    else
    {
         updateSetting(_type, (sval=="ON") );
    }
}

void StdfConfig::updateSetting(const string type, bool bval) {

    if(type == "ATR")
    {
        stdf_fields_setting[ATR] = bval;
    }
    else if(type == "BPS")
    {
        stdf_fields_setting[BPS] = bval;
    }
    else if(type == "DTR")
    {
        stdf_fields_setting[DTR] = bval;
    }
    else if(type == "EPS")
    {
        stdf_fields_setting[EPS] = bval;
    }
    else if(type == "FAR")
    {
        stdf_fields_setting[FAR] = bval;
    }
    else if(type == "FTR")
    {
        stdf_fields_setting[FTR] = bval;
    }
    else if(type == "GDR")
    {
        stdf_fields_setting[GDR] = bval;
    }
    else if(type == "HBR")
    {
        stdf_fields_setting[HBR] = bval;
    }
    else if(type == "MIR")
    {
        stdf_fields_setting[MIR] = bval;
    }
    else if(type == "MPR")
    {
        stdf_fields_setting[MPR] = bval;
    }
    else if(type == "MRR")
    {
        stdf_fields_setting[MRR] = bval;
    }
    else if(type == "PCR")
    {
        stdf_fields_setting[PCR] = bval;
    }
    else if(type == "PGR")
    {
        stdf_fields_setting[PGR] = bval;
    }
    else if(type == "PIR")
    {
        stdf_fields_setting[PIR] = bval;
    }
    else if(type == "PLR")
    {
        stdf_fields_setting[PLR] = bval;
    }
    else if(type == "PMR")
    {
        stdf_fields_setting[PMR] = bval;
    }
    else if(type == "PRR")
    {
        stdf_fields_setting[PRR] = bval;
    }
    else if(type == "PTR")
    {
        stdf_fields_setting[PTR] = bval;
    }
    else if(type == "RDR")
    {
        stdf_fields_setting[RDR] = bval;
    }
    else if(type == "SBR")
    {
        stdf_fields_setting[SBR] = bval;
    }
    else if(type == "SDR")
    {
        stdf_fields_setting[SDR] = bval;
    }
    else if(type == "TSR")
    {
        stdf_fields_setting[TSR] = bval;
    }
    else if(type == "WCR")
    {
        stdf_fields_setting[WCR] = bval;
    }
    else if(type == "WIR")
    {
        stdf_fields_setting[WIR] = bval;
    }
    else if(type == "WRR")
    {
        stdf_fields_setting[WRR] = bval;
    }
    else if(type == "DEBUG") {
        debug = bval;
    }
}

bool StdfConfig::getRecSetting(stdf_rec rec) const
{
    map<int,bool>::const_iterator it;
    it = stdf_fields_setting.find(rec);
    return it->second;
}

string StdfConfig::getFilename() const
{
    return  sFileName;
}

string StdfConfig::getDestDir() const
{
    return sDesDir;
}

string StdfConfig::getSrcDir() const
{
    return sSrcDir;
}

void StdfConfig::setFilename(const string& s)
{
    if( !s.empty()) {
        sSrcDir = ".";
        sFileName = s;
    }
}

bool StdfConfig::hasTestNumbers() const {
    return ((int) test_numbers_setting.size()) > 0;
}

vector<int> StdfConfig::getTestNumbersSetting() const {
    vector<int> res;
    res = test_numbers_setting;  // using '=' copy consturctor
    return res;  // return copy
}


void StdfConfig::setTestNumbers(vector<int> list) {
    if ( ((int) list.size()) >0)
        test_numbers_setting = list;
}


void StdfConfig::setStdfFieldsSetting(vector<string> stdffields) {

    if ( ((int)stdffields.size()) < 1)
        return;   // do nothing

    // change all stdf fields required to false
    stdfFieldsRecSettingInitializeAs(false);

    // iterate list and turn on only those that exist
    vector<string>::const_iterator it;
    for (it=stdffields.begin(); it!=stdffields.end(); it++) {
       updateSetting(*it, true);
    }
}

void StdfConfig::stdfFieldsRecSettingInitializeAs(bool flag) {

   stdf_fields_setting[ATR] = flag;
   stdf_fields_setting[BPS] = flag;
   stdf_fields_setting[DTR] = flag;
   stdf_fields_setting[EPS] = flag;
   stdf_fields_setting[FAR] = flag;
   stdf_fields_setting[FTR] = flag;
   stdf_fields_setting[GDR] = flag;
   stdf_fields_setting[HBR] = flag;
   stdf_fields_setting[MIR] = flag;
   stdf_fields_setting[MPR] = flag;
   stdf_fields_setting[MRR] = flag;
   stdf_fields_setting[PCR] = flag;
   stdf_fields_setting[PGR] = flag;
   stdf_fields_setting[PIR] = flag;
   stdf_fields_setting[PLR] = flag;
   stdf_fields_setting[PMR] = flag;
   stdf_fields_setting[PRR] = flag;
   stdf_fields_setting[PTR] = flag;
   stdf_fields_setting[RDR] = flag;
   stdf_fields_setting[SBR] = flag;
   stdf_fields_setting[SDR] = flag;
   stdf_fields_setting[TSR] = flag;
   stdf_fields_setting[WCR] = flag;
   stdf_fields_setting[WIR] = flag;
   stdf_fields_setting[WRR] = flag;
}

bool StdfConfig::getIsDebugSwitchSet() const {
    return debug;
}
